package com.wsoft.bpm.listener.execute;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.Opt;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.wsoft.bpm.entity.ActWorkflowConfigEntity;
import com.wsoft.bpm.query.node.TerminateEndEventQuery;
import com.wsoft.bpm.service.ActivityCallAble;
import com.wsoft.bpm.service.IActWorkflowConfigService;
import com.wsoft.constant.CommonConstant;
import com.wsoft.entity.BaseEntity;
import org.activiti.bpmn.model.CallActivity;
import org.activiti.bpmn.model.FlowElement;
import org.activiti.bpmn.model.SubProcess;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.delegate.DelegateExecution;
import org.activiti.engine.delegate.ExecutionListener;
import org.activiti.engine.impl.context.Context;
import org.activiti.engine.repository.ProcessDefinition;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;

/**
 * 流程终结回调监听器
 *
 * @Author zhonglj
 * @Date 2024-09-23 15:43
 */
@Component("processTerminateEndCallBackListener")
public class ProcessTerminateEndCallBackListener implements ExecutionListener {
    @Resource
    private RepositoryService repositoryService;
    @Resource
    private IActWorkflowConfigService workflowConfigService;

    @Override
    public void notify(DelegateExecution execution) {
        if (isInChildProcess(execution)) {
            // 如果是处于子流程中，不需要操作业务数据
            return;
        }

        ActWorkflowConfigEntity terminateEndConfig = workflowConfigService.getOne(Wrappers.lambdaQuery(ActWorkflowConfigEntity.class)
                .eq(ActWorkflowConfigEntity::getActId, execution.getCurrentActivityId())
                .eq(ActWorkflowConfigEntity::getProcDefId, execution.getProcessDefinitionId())
                .eq(BaseEntity::getDeleted, CommonConstant.YESNO_NO)
        );

        if (terminateEndConfig == null || StrUtil.isBlank(terminateEndConfig.getJson())) {
            return;
        }

        TerminateEndEventQuery req = BeanUtil.toBean(JSONUtil.parseObj(terminateEndConfig.getJson()), TerminateEndEventQuery.class);
        if (req.isTerminateAll()) {
            ProcessDefinition processDefinition = repositoryService
                    .createProcessDefinitionQuery()
                    .processDefinitionId(execution.getProcessDefinitionId())
                    .singleResult();
            //回调完成
            ActivityCallAble callService = ActivityCallAble.findCallService(processDefinition.getKey());
            if (callService != null) {
                callService.callTerminate(processDefinition.getKey(), execution.getProcessInstanceId(), execution.getProcessInstanceBusinessKey());
            }
        }

    }

    public boolean isInChildProcess(DelegateExecution execution) {
        while (execution != null) {
            FlowElement currentFlowElement = execution.getCurrentFlowElement();
            if (currentFlowElement instanceof SubProcess) {
                // 找到一个subProcess，说明在内嵌子流程中
                return true;
            }
            if (currentFlowElement instanceof CallActivity) {
                // 找到一个CallActivity，说明在调用活动中
                return true;
            }

            // 获取父级执行
            String parentExecutionId = Opt.ofNullable(execution.getParentId()).orElse(execution.getSuperExecutionId());
            execution = Context.getCommandContext().getExecutionEntityManager().findById(parentExecutionId);
        }

        return false;
    }
}
